<template>
	<div class="ywgzt-container">
		<el-row :gutter="10" class="h-100">
			<el-col :span="5" class="h-100">
				<div class="index-container-left">
					<!-- 最新失败业务告警 -->
					<div class="left-box">
						<div class="business-list-header">
							<div class="business-list-title"><img src="~@/assets/icons/png/ops-workbench/index/alert.png" class="icon" />最新失败业务告警</div>
							<div>
								<el-link :underline="false" @click="handleToRealTimeAlarm(2)">更多></el-link>
							</div>
						</div>
						<div class="business-list-body">
							<div v-show="active.failRateAlarm" class="no-data-box">
								<svg-icon class-name="nodata" icon-class="nodata" style="width: 1.2rem"></svg-icon>
								<span style="padding-left: 5px">暂无告警数据~</span>
							</div>
							<transition-group name="flip-list" tag="div" class="flip-list-box">
								<div
									v-for="item in busiFailList"
									:key="item.dataType != 3 && item.dataType != 4 ? item.businessCode : item.stepCode"
									:class="'business-list-item transition-' + item.pos"
									@click="jumpToAlarmAnalysis(item, '2')"
								>
									<div class="list-index">{{ busiFailList.indexOf(item) + 1 }}</div>
									<div class="business-list-content">
										<el-row class="list-content-data">
											<el-col :span="10">{{ item.pushTime }}</el-col>
											<el-col :span="8">
												失败率：<span class="data-text">{{ item.failRate == 100 ? Number(item.failRate) : item.failRate }}%</span>
											</el-col>
											<el-col :span="6">
												笔数：<span class="data-text">{{ item.records }}</span>
											</el-col>
										</el-row>
										<div
											v-if="item.dataType != 3 && item.dataType != 4"
											class="list-content-label"
											:title="'[' + item.systemName + ']' + '[' + item.businessName + ']'"
										>
											<span>［{{ item.systemName }}］</span>
											<span>［{{ item.businessName }}］</span>
										</div>
										<div v-else class="list-content-label" :title="'[' + item.stepName + ']'">
											<span>［{{ item.stepName }}］</span>
										</div>
									</div>
								</div>
							</transition-group>
						</div>
					</div>
					<!-- 最新响应慢业务告警 -->
					<div class="left-box">
						<div class="business-list-header">
							<div class="business-list-title"><img src="~@/assets/icons/png/ops-workbench/index/time.png" class="icon" />最新响应慢业务告警</div>
							<div>
								<el-link :underline="false" @click="handleToRealTimeAlarm(1)">更多></el-link>
							</div>
						</div>
						<div class="business-list-body">
							<div v-show="active.responseTimeAlarm" class="no-data-box">
								<svg-icon class-name="nodata" icon-class="nodata" style="width: 1.2rem"></svg-icon>
								<span style="padding-left: 5px">暂无告警数据~</span>
							</div>
							<transition-group name="flip-list" tag="div" class="flip-list-box">
								<div
									v-for="item in busiLongTimeList"
									:key="item.dataType != 3 && item.dataType != 4 ? item.businessCode : item.stepCode"
									:class="'business-list-item transition-' + item.pos"
									@click="jumpToAlarmAnalysis(item, '1')"
								>
									<div class="list-index">{{ busiLongTimeList.indexOf(item) + 1 }}</div>
									<div class="business-list-content">
										<el-row class="list-content-data">
											<el-col :span="10">{{ item.pushTime }}</el-col>
											<el-col :span="9">
												响应慢比例：
												<span class="data-text">{{ item.dealTimeAlarmRate == 100 ? Number(item.dealTimeAlarmRate) : item.dealTimeAlarmRate }}%</span>
											</el-col>
											<el-col :span="5">
												笔数：<span class="data-text">{{ item.records }}</span>
											</el-col>
										</el-row>
										<div
											v-if="item.dataType != 3 && item.dataType != 4"
											class="list-content-label"
											:title="'[' + item.systemName + ']' + '[' + item.businessName + ']'"
										>
											<span>［{{ item.systemName }}］</span>
											<span>［{{ item.businessName }}］</span>
										</div>
										<div v-else class="list-content-label" :title="'[' + item.stepName + ']'">
											<span>［{{ item.stepName }}］</span>
										</div>
									</div>
								</div>
							</transition-group>
						</div>
					</div>
				</div>
			</el-col>
			<el-col :span="19" class="h-100">
				<div class="index-container-right">
					<el-row class="center-box">
						<el-col :span="13" class="center-box-left">
							<!-- 系统数据总览 -->
							<div class="center-head">
								<div class="system-overview-item">
									<div class="system-item-header">
										<img src="~@/assets/icons/png/ops-workbench/index/yewuxitong.png" class="system-icon" />业务系统
									</div>
									<div class="system-item-content">
										<div class="item-content-data">
											<div class="item-data-label">异常</div>
											<div class="system-item-data text-red">
												<count-to
													:start-val="firstQuery ? 0 : oldOverview.systemUnhealthTotal"
													:end-val="systemOverview.systemUnhealthTotal ? systemOverview.systemUnhealthTotal : 0"
													:duration="2000"
												/>
											</div>
										</div>
										<div class="item-content-data">
											<div class="item-data-label">总数</div>
											<div class="system-item-data">
												<count-to
													:start-val="firstQuery ? 0 : oldOverview.systemTotal"
													:end-val="systemOverview.systemTotal ? systemOverview.systemTotal : 0"
													:duration="2000"
												/>
											</div>
										</div>
									</div>
								</div>
								<div class="divider"></div>
								<div class="system-overview-item">
									<div class="system-item-header">
										<img src="~@/assets/icons/png/ops-workbench/index/yingyongzujian.png" class="system-icon" />应用组件
									</div>
									<div class="system-item-content">
										<div class="item-content-data">
											<div class="item-data-label">异常</div>
											<div class="system-item-data text-red">
												<count-to
													:start-val="firstQuery ? 0 : oldOverview.segmentUnhealthTotal"
													:end-val="systemOverview.segmentUnhealthTotal ? systemOverview.segmentUnhealthTotal : 0"
													:duration="2000"
												/>
											</div>
										</div>
										<div class="item-content-data">
											<div class="item-data-label">总数</div>
											<div class="system-item-data">
												<count-to
													:start-val="firstQuery ? 0 : oldOverview.segmentTotal"
													:end-val="systemOverview.segmentTotal ? systemOverview.segmentTotal : 0"
													:duration="2000"
												/>
											</div>
										</div>
									</div>
								</div>
								<div class="divider"></div>
								<div class="system-overview-item">
									<div class="system-item-header"><img src="~@/assets/icons/png/ops-workbench/index/yewu.png" class="system-icon" />业务</div>
									<div class="system-item-content">
										<div class="item-content-data">
											<div class="item-data-label">异常</div>
											<div class="system-item-data text-red">
												<count-to
													:start-val="firstQuery ? 0 : oldOverview.businessUnhealthTotal"
													:end-val="systemOverview.businessUnhealthTotal ? systemOverview.businessUnhealthTotal : 0"
													:duration="2000"
												/>
											</div>
										</div>
										<div class="item-content-data">
											<div class="item-data-label">总数</div>
											<div class="system-item-data">
												<count-to
													:start-val="firstQuery ? 0 : oldOverview.businessTotal"
													:end-val="systemOverview.businessTotal ? systemOverview.businessTotal : 0"
													:duration="2000"
												/>
											</div>
										</div>
									</div>
								</div>
								<div class="divider"></div>
								<div class="system-overview-item">
									<div class="system-item-header">
										<img src="~@/assets/icons/png/ops-workbench/index/yewufangwenliang.png" class="system-icon" />业务访问量
									</div>
									<div class="system-item-content">
										<div class="item-content-data">
											<div class="item-data-label">异常</div>
											<div class="system-item-data text-red">
												<count-to
													:start-val="firstQuery ? 0 : oldOverview.businessVisitUnhealthTotal"
													:end-val="systemOverview.businessVisitUnhealthTotal ? systemOverview.businessVisitUnhealthTotal : 0"
													:duration="2000"
												/>
											</div>
										</div>
										<div class="item-content-data">
											<div class="item-data-label">总数</div>
											<div class="system-item-data">
												<count-to
													:start-val="firstQuery ? 0 : oldOverview.businessVisitTotal"
													:end-val="systemOverview.businessVisitTotal ? systemOverview.businessVisitTotal : 0"
													:duration="2000"
												/>
											</div>
										</div>
									</div>
								</div>
								<div class="divider"></div>
								<div class="system-overview-item">
									<div class="system-item-header"><img src="~@/assets/icons/png/ops-workbench/index/yonghushu.png" class="system-icon" />用户数</div>
									<div class="system-item-content">
										<div class="user-total-text">
											<count-to :start-val="firstQuery ? 0 : oldOverview.userTotal" :end-val="systemOverview.userTotal || 0" :duration="2000" />
										</div>
									</div>
								</div>
							</div>
							<!-- 区域分布 -->
							<el-row class="center-body">
								<div class="toggle-tab-content">
									<!-- 地图-区域分布 -->
									<div v-show="active.areaMap" class="map-container">
										<div id="map" class="chartStyle">地图-区域分布</div>
										<!-- 区域业务统计 -->
										<div class="area-busi-table-container">
											<el-table size="small" :data="areaBusiData" height="90%" class="area-business-table">
												<el-table-column align="center" prop="areaName" label="城市" min-width="3" :show-overflow-tooltip="true">
													<template #default="scope">
														<span>{{ scope.row.areaName }}</span>
													</template>
												</el-table-column>
												<el-table-column align="center" prop="completeCount" label="受理量" min-width="3">
													<template #default="scope">
														<span>{{ scope.row.completeCount || '-' }}</span>
													</template>
												</el-table-column>
												<el-table-column align="center" prop="alarmCount" label="告警量" min-width="3">
													<template #default="scope">
														<span>{{ scope.row.alarmCount || '-' }}</span>
													</template>
												</el-table-column>
											</el-table>
											<!-- 底部翻页 -->
											<div class="turn-page-box">
												<div
													v-for="i in areaBusiTablePage.totalPage"
													:key="i"
													class="page-item"
													:class="{ 'page-item-active': areaBusiTablePage.pageNum === i }"
													:style="{ width: areaBusiTablePage.pageItemWidth + 'px' }"
													@click="areaBusiTableChangePage(i)"
												></div>
											</div>
										</div>
									</div>
								</div>
							</el-row>
						</el-col>
						<el-col :span="11" class="center-box-right">
							<!-- 系统切换 -->
							<el-row class="banner-box">
								<el-col :span="12" class="banner-toggle-box">
									<el-select v-model="queryParams.systemId" size="large" popper-class="ywgzt-select" @change="handleSystemChange">
										<el-option v-for="option in systemOptions" :key="option.value" :value="option.value" :label="option.label"></el-option>
									</el-select>
								</el-col>
								<el-col :span="12">
									<el-row>
										<el-col :span="3">
											<el-popover placement="bottom" trigger="click" :width="500" popper-class="search-system-popover" @show="handleSystemSearchShow">
												<div class="search-system-container">
													<el-row>
														<el-input v-model="querySystemName" placeholder="请输入系统名称" clearable style="width: 280px; margin-right: 5px">
															<template #prefix>
																<el-icon class="el-input__icon"><search /></el-icon>
															</template>
														</el-input>
														<el-button class="query-system-btn" @click="handleSearchSystemHealth('filter')">系统筛选</el-button>
													</el-row>
													<el-row class="domain-title">系统分类</el-row>
													<el-row>
														<el-link
															v-for="domain in systemDomainOptions"
															:key="domain.systemDomainId"
															:underline="false"
															:class="systemDomainId == domain.systemDomainId ? 'active-domain' : 'unActive-domain'"
															@click="handleSearchSystemHealth(domain.systemDomainId)"
															>{{ domain.systemDomainName }}</el-link
														>
													</el-row>
													<div class="system-health-pie-box">
														<div v-show="active.healthRateAlarmNoData" class="no-data-box">
															<svg-icon class-name="nodata" icon-class="nodata" style="width: 1.2rem"></svg-icon>
															<span style="padding-left: 5px">暂无告警数据~</span>
														</div>
														<div v-for="d in systemHealthArr" :id="'chart-' + d.systemId" :key="d.systemId" class="chart-item"></div>
													</div>
												</div>
												<template #reference>
													<el-link :underline="false" class="banner-icon-box">
														<img src="~@/assets/icons/png/ops-workbench/index/search.png" class="banner-icon" />
													</el-link>
												</template>
											</el-popover>
										</el-col>
										<el-col :span="2">
											<el-link :underline="false" class="banner-icon-box" @click="allRefresh">
												<img src="~@/assets/icons/png/ops-workbench/index/refresh.png" class="banner-icon" />
											</el-link>
										</el-col>
										<el-col :span="4">
											<!-- <el-popover placement="bottom" trigger="click" :width="300" popper-class="search-system-popover" @show="handleRefreshShow">
												<el-row class="set-refresh-box">
													<el-col :span="12">
														<el-switch v-model="refreshFlag" active-text="自动刷新" @change="updateRefresh"></el-switch>
													</el-col>
													<el-col :span="12">
														<el-input-number
															v-model.number="interval.allRefreshTime"
															:step="1"
															:min="5"
															:max="9999"
															:precision="0"
															size="small"
															style="width: 100px; margin-right: 10px"
															@blur="onRefreshChange"
														></el-input-number
														>秒
													</el-col>
												</el-row>
												<template #reference>
													<el-link :underline="false" class="banner-icon-box">
														<img src="~@/assets/icons/png/ops-workbench/index/set.png" class="banner-icon" />
													</el-link>
												</template>
											</el-popover> -->
											<div class="countdown-clock">{{ countdown }}</div>
										</el-col>
										<el-col :span="8">
											<el-link :underline="false" class="banner-icon-box" @click="jumpToHisAlarm">
												<img src="~@/assets/icons/png/ops-workbench/index/history.png" class="banner-icon" />历史告警
											</el-link>
										</el-col>
										<el-col :span="6">
											<el-link :underline="false" class="banner-icon-box" @click="switchTab">
												<img src="~@/assets/icons/png/ops-workbench/index/switch.png" class="banner-icon" />切换
											</el-link>
										</el-col>
									</el-row>
								</el-col>
							</el-row>
							<el-row class="right-chart-box">
								<observation-area
									ref="observationRef"
									v-model:showObservationArea="showObservationArea"
									v-model:queryParams="queryParams"
								></observation-area>
							</el-row>
							<el-row class="right-list-box">
								<div class="health-list-header">
									<div class="health-list-title">
										<div class="circle"></div>
										最新健康度告警
									</div>
									<div class="health-list-label">
										<div class="health-more">
											<el-link :underline="false" @click="handleToRealTimeAlarm(3)">更多></el-link>
										</div>
									</div>
								</div>
								<div class="health-list-body">
									<div v-show="active.healthRateAlarm" class="no-data-box">
										<svg-icon class-name="nodata" icon-class="nodata" style="width: 1.2rem"></svg-icon>
										<span style="padding-left: 5px">暂无告警数据~</span>
									</div>
									<transition-group name="flip-list" tag="div" class="flip-list-box">
										<div
											v-for="item in healthAlertList"
											:key="item.businessCode"
											:class="'health-list-item healthTransition-' + item.pos"
											@click="jumpToAlarmAnalysis(item, '3')"
										>
											<el-row class="list-content-label" :title="item.systemName + '-' + item.businessName">
												{{ item.systemName }}-{{ item.businessName }}
											</el-row>
											<el-row class="list-content-data">
												<el-col :span="15">{{ item.maxAlarmTime.substring(0, 19) }}</el-col>
												<el-col :span="5"
													>健康度： {{ item.newestHealthRate == 100 ? Number(item.newestHealthRate) : item.newestHealthRate }}%</el-col
												>
												<el-col :span="4">失败率： {{ item.newestFailRate == 100 ? Number(item.newestFailRate) : item.newestFailRate }}%</el-col>
											</el-row>
										</div>
									</transition-group>
								</div>
							</el-row>
						</el-col>
					</el-row>
					<!-- 访问量及告警量折线图 -->
					<el-row class="footer-box">
						<div class="trend-toggle-row">
							<span class="trend-title">时间窗口&nbsp;&nbsp;</span>
							<el-select v-model="trendType" popper-class="ywgzt-select" size="small" @change="toggleTrendScale">
								<el-option v-for="option in trendOptions" :key="option.value" :value="option.value" :label="option.label"></el-option>
							</el-select>
						</div>
						<div id="alertBar" class="trend-chart"></div>
					</el-row>
				</div>
			</el-col>
		</el-row>

		<!-- 三个实时告警的更多-弹框 -->
		<el-dialog
			:key="realtimeDialogKey"
			v-model="realtimeDialogOpen"
			:title="realtimeDialogTitle"
			width="1500px"
			:close-on-click-modal="false"
			:append-to-body="true"
			custom-class="ywgzt-dialog"
			@opend="handleOpenRealtimeDialog"
			@closed="handleCloseRealtimeDialog"
		>
			<realtime-dialog ref="realtimeDialog" :params="realTimeParam" @close="setDialogClose"></realtime-dialog>
		</el-dialog>
	</div>
</template>

<script setup name="YwgztIndex" lang="ts">
import { CountTo } from 'vue3-count-to';
import axios from 'axios';
import * as echarts from 'echarts';
import 'echarts-liquidfill';
import ObservationArea from '@/views/ops-workbench/index-more/observation-area/index.vue';
import RealtimeDialog from '@/views/ops-workbench/index-more/realtime-dialog/index.vue';
import { parseTime, lineFeed, deepCloneOps, randomUUID } from '@/utils/common';
import { noDataOption } from '@/utils/chartNoData';
import {
	queryAreaBusinessStatistics,
	queryMapAreaBusinessStatistics,
	queryRecentHealthRateAlarm,
	queryCompleteAlarmTrend,
	queryRefreshConfig,
	updateRefreshConfig,
	querySystemOverview,
	querySystemDomainOption,
	getSystemHealthList,
} from '@/api/ops-workbench/index';
import { queryNewestAlarmList } from '@/api/ops-workbench/index-more/realtimeDialog';
import { queryAppSystemOptions } from '@/api/search/searchOptions';
import { getConfigKey } from '@/api/management/systemManage/systemConfig';
import { chartResize, getGeo, fillCity, getAreaStyle, getTrendTimeRange } from '@/utils/ops-workbench/chartCommon';
import chinaData from '/public/Echart/map/china.json';
import useShareYwgztDataStore from '@/store/ops-workbench/shareYwgztData';
import useAppStore from '@/store/modules/app';
import { onActivated, onDeactivated, reactive, ref, watch, onMounted, onUnmounted, getCurrentInstance } from 'vue';
import { useRouter } from 'vue-router';
import useCurrentInstance from '@/utils/useCurrentInstance';
import useUserStore from '@/store/modules/userinfo';

const { proxy } = useCurrentInstance();
const router = useRouter();
const shareDataStore = useShareYwgztDataStore();
echarts.registerMap('china', chinaData);
const observationRef = ref<any>();
const realtimeDialog = ref<any>();

// 请求参数
let queryParams = reactive<anyObj>({
	systemId: '',
	startTime: '',
	endTime: '',
});
let alarmQueryTime = reactive({
	startTime: '',
	endTime: '',
});
let areaQueryTime = reactive({
	startTime: '',
	endTime: '',
});
let place = 'jiangxi';
// 地理位置数据
let geoCoordMap: anyObj;
// 切换激活
let active = reactive({
	areaMap: true,
	failRateAlarm: false,
	responseTimeAlarm: false,
	healthRateAlarm: false,
	healthRateAlarmNoData: false,
});
// 图表对象
type ChartType = {
	map: any;
	alertBar: any;
};
let chart: ChartType = {
	map: null,
	alertBar: null,
};
// 区域业务量表格分页
let areaBusiTablePage = reactive({
	totalPage: 0,
	pageNum: 1,
	pageSize: 5,
	pageItemWidth: 0,
});
// 定时器
let interval = reactive<{
	allRefresh: any;
	allRefreshTime: number;
	autoChangePage: any;
}>({
	// 全局刷新
	allRefresh: null,
	// 全局刷新时间，默认60秒
	allRefreshTime: 60,
	// 自动换页
	autoChangePage: null,
});
// 系统下拉框列表数据
const systemOptions = ref<anyObj[]>([]);
// 区域业务量表格展示数据
const areaBusiData = ref([]);
// 区域业务量表格总数据
const areaBusiDataTemp = ref([]);
// 失败率高的业务列表数据
const busiFailList = ref<anyObj[]>([]);
// 响应慢的业务列表数据
const busiLongTimeList = ref<anyObj[]>([]);
// 健康度告警列表数据
const healthAlertList = ref<anyObj[]>([]);
// 页面刷新设置-是否自动刷新
const refreshFlag = ref(true);
// 系统总览数据
const systemOverview: anyObj = ref({});
const firstQuery = ref(true);
// 上一次系统总览数据
const oldOverview: anyObj = ref({});
// 系统分类数据
const systemDomainOptions = ref<anyObj[]>([]);
// 系统健康度列表数据
const systemHealthArr = ref<anyObj[]>([]);
const systemHealthArrAllData = ref([]);
// 系统筛选的系统名称
const querySystemName = ref('');
// 选中的系统分类
const systemDomainId = ref<string | number>();
// 判断趋势图前一次是否为无数据,是的话当有数据时渲染之前要先clear一下图形,不然会出现"暂无数据"和有数据同时渲染问题
const lastNoData = ref(false);
// 趋势图当前展示时间范围 1:最近一小时, 2当天
const trendType = ref(1);
const trendOptions = ref([
	{ label: '1小时', value: 1 },
	{ label: '4小时', value: 4 },
	{ label: '8小时', value: 8 },
	{ label: '12小时', value: 12 },
	{ label: '当天', value: 2 },
]);
// 最后一次的刷新时间
let finalRefreshVal: number;
// 刷新时间加/减按钮
const increaseEle = ref<HTMLElement>();
const decreaseEle = ref<HTMLElement>();
// 切换按钮
const showObservationArea = ref(false);
// 三个实时告警更多弹框的相关参数
const realtimeDialogKey = ref(randomUUID());
const realtimeDialogTitle = ref('');
const realTimeParam = ref({});
const realtimeDialogOpen = ref(false);
let openWatcher: any; //用户存储侧边栏watcher
let websock: anyObj;
const countdown = ref(60);

onMounted(() => {
	window.addEventListener('resize', handleChartResize);
	getConfigKey('sys.project.map').then((response: ApiResponse) => {
		place = response.data;
		geoCoordMap = getGeo(place);
		// 初始化图表对象
		initChart();
		// 请求所有echart图表相关数据并渲染，获取到systemId
		getSystemOption();
		getMapBusiData();
		// 请求页面所有数据,要获取到systemId才能获取到全部数据
		getAllData();
	});
});
onUnmounted(() => {
	// 跳转到其他页面时确保定时器已销毁
	stopAllRefreshInterval();
	clearInterval(interval.autoChangePage);
	if (websock) {
		websock.close(); // 关闭websocket
	}
});
onActivated(() => {
	handleChartResize();
	window.addEventListener('resize', handleChartResize);
	// 重新赋值watch
	openWatcher = watch(
		() => useAppStore().sidebar.opened,
		() => {
			// 监听侧边栏收缩展开状态
			setTimeout(() => {
				// 添加resize监听器,自适应图表大小
				handleChartResize();
			}, 200);
		}
	);
});
onDeactivated(() => {
	window.removeEventListener('resize', handleChartResize);
	// 调用watch的方法把watcher注销掉
	openWatcher();
});

// 动画效果-1.移除指定下标
function slipListRemove(key: any, inxArr: number[]) {
	inxArr.forEach((inx: number, index: number) => {
		key.value.splice(inx - index, 1);
	});
}
// 移除原有超出长度的
function slipListRemove2(key: any, l: number) {
	for (let i = 0; i < l; i++) {
		key.value.pop();
	}
}
// 动画效果-2.移动
function moveSlipList(key: any, dLen: number) {
	setTimeout(() => {
		// 待插入数组的长度
		const kLenPos = dLen;
		// 移除后剩下的原数组数据往后挪出 待插入数组长度 的位置
		key.value.forEach((r: anyObj, index: number) => {
			r.pos = kLenPos + index;
		});
	}, 300);
}
// 动画效果-3.头部插入
function slipListAdd(key: any, dataArr: anyObj[], len: number) {
	if (len === undefined) {
		len = 8;
	}
	let delayTime = 600;
	let l = dataArr.length + key.value.length - len;
	if (l > 0) {
		slipListRemove2(key, l);
	}
	moveSlipList(key, dataArr.length);
	setTimeout(() => {
		const dLenPos = dataArr.length - 1;
		dataArr.forEach((r, index) => {
			r.pos = dLenPos - index;
			key.value.splice(0, 0, r);
			if (key.value.length > len) {
				slipListRemove2(key, 1);
			}
		});
	}, delayTime);
}
// 动画效果-4.请求有新数据的插入逻辑
function refreshAlarmListData(key: any, resData: anyObj[], timeKey: string, len: number) {
	const isSameDayFlag = isSameDay(key.value[0][timeKey]);
	if (!isSameDayFlag) {
		// 不同天时清空前一天全部数据
		slipListRemove2(key, key.value.length);
	}
	const inxArr: number[] = [],
		dataArr: anyObj[] = []; // 原数组待删除数据下标、待插入新数据反转
	const sameArr: anyObj[] = [],
		insertArr: anyObj[] = [],
		codes: anyObj[] = [],
		steps: anyObj[] = []; // 与原数组有相同的数据、待插入新数据、原数组的业务编码、原数组的stepCode
	// 找出请求数据中原数组没有的businessCode的业务数据
	for (let i = 0; i < key.value.length; i++) {
		codes.push(key.value[i].businessCode);
		steps.push(key.value[i].stepCode);
	}
	resData.forEach((d: anyObj) => {
		if (codes.indexOf(d.businessCode) < 0) {
			insertArr.push(d); // 待插入的 没有相同业务的数据(含所有公共步骤/接口)
		}
	});
	// 如果当前数组已有业务与新请求的业务相同时间不同,sameArr就存入那个业务数据对象
	for (let i = 0; i < key.value.length; i++) {
		resData.forEach((d: anyObj) => {
			if (key.value[i].businessCode === d.businessCode && key.value[i][timeKey] !== d[timeKey]) {
				sameArr.push(key.value[i]);
				insertArr.push(d); // 待插入数据（含相同业务）
				return;
			}
		});
	}

	// 新增处理：是否有相同共用接口/步骤：dataType为3/4的
	if (insertArr.some((s) => s.dataType === 3 || s.dataType === 4) && steps.length > 0) {
		insertArr.forEach((d) => {
			if ((d.dataType === 3 || d.dataType === 4) && steps.indexOf(d.stepCode) > 0) {
				sameArr.push(key.value.find((k: anyObj) => k.stepCode === d.stepCode));
			}
		});
	}

	if (sameArr.length > 0) {
		// 有相同业务,去掉当前数组原位置的那条数据,再往头部插入新传入的数据
		sameArr.forEach((same) => {
			inxArr.push(key.value.indexOf(same));
		});
		insertArr.reverse().forEach((r) => {
			dataArr.push(r);
		});
		slipListRemove(key, inxArr);
		slipListAdd(key, dataArr, len);
	} else {
		// 没有相同业务,直接插入到当前数组头部
		insertArr.reverse().forEach((r) => {
			dataArr.push(r);
		});
		slipListAdd(key, dataArr, len);
	}
}
// 判断是否同天
function isSameDay(oldDate: string) {
	const oldDay = new Date(oldDate);
	const newDay = new Date(queryParams.startTime);
	const oldTimeStr = oldDay.getFullYear() + '-' + oldDay.getMonth() + '-' + oldDay.getDate();
	const newTimeStr = newDay.getFullYear() + '-' + newDay.getMonth() + '-' + newDay.getDate();
	return oldTimeStr === newTimeStr;
}

/*1.初始化*/
// 初始化请求参数
function initParams() {
	const currentDate = new Date();
	// 告警的请求时间 最近5分钟
	alarmQueryTime.startTime = parseTime(currentDate.getTime() - 1000 * 300, '{y}-{m}-{d} {h}:{i}:00');
	alarmQueryTime.endTime = parseTime(currentDate.getTime(), '{y}-{m}-{d} {h}:{i}:00');
	// 其他的请求时间 当天0点至当前
	queryParams.startTime = parseTime(currentDate.getTime(), '{y}-{m}-{d}') + ' 00:00:00';
	queryParams.endTime = parseTime(currentDate.getTime(), '{y}-{m}-{d} {h}:{i}:00');
	// 地图数据请求时间为最近一小时
	areaQueryTime.startTime = parseTime(currentDate.getTime() - 1000 * 3600, '{y}-{m}-{d} {h}:{i}:00');
	areaQueryTime.endTime = parseTime(currentDate.getTime(), '{y}-{m}-{d} {h}:{i}:00');
}
// 初始化图表对象
function initChart() {
	let base = import.meta.env.VITE_APP_ASSETS_BASEURL;
	chart.map = echarts.init(document.getElementById('map')!);
	chart.alertBar = echarts.init(document.getElementById('alertBar')!);
	observationRef.value.initChart();
	axios.get(`${base}/Echart/map/json/province/${place}.json`).then((res) => {
		echarts.registerMap(place, res.data);
	});
}
// 自适应图表大小
function handleChartResize() {
	chartResize(chart);
	observationRef.value.handleChartResize();
}

/*2.请求数据*/
// 请求所有数据
function getAllData() {
	getBusiFailList();
	getBusiLongTimeList();
	getAreaBusiData();
	getSystemOverview();
	getRefreshConfig();
	getSystemDomainOption();
}
// 获取最新失败率告警的列表数据
function getBusiFailList() {
	queryNewestAlarmList({
		startTime: queryParams.startTime,
		endTime: queryParams.endTime,
		pageNum: 1,
		pageSize: 8,
		alarmIndicatorCode: 'BS_FAIL_RATE_10',
		isHomePage: 1,
	}).then((res: ApiResponse) => {
		if (res.code !== 0) {
			active.failRateAlarm = true;
			return;
		}
		// 都无数据时展示
		if (!(busiFailList.value.length || res.data.data.length)) {
			active.failRateAlarm = true;
			return;
		}
		active.failRateAlarm = false;
		// 请求有数据时
		// 1. 当前数组没有数据
		if (busiFailList.value.length <= 0) {
			const dLenPos = res.data.data.length - 1;
			res.data.data.reverse().forEach((r: anyObj, index: number) => {
				r.pos = dLenPos - index;
				busiFailList.value.splice(0, 0, r);
			});
			return;
		}
		// 2. 当前数组有数据
		refreshAlarmListData(busiFailList, res.data.data, 'pushTime', 8);
	});
}
// 获取最新响应慢的列表数据
function getBusiLongTimeList() {
	queryNewestAlarmList({
		startTime: queryParams.startTime,
		endTime: queryParams.endTime,
		pageNum: 1,
		pageSize: 8,
		alarmIndicatorCode: 'BS_FAIL_RATE_20',
		isHomePage: 1,
	}).then((res: ApiResponse) => {
		if (res.code !== 0) {
			active.responseTimeAlarm = true;
			return;
		}
		// 都无数据时展示
		if (!(busiLongTimeList.value.length || res.data.data.length)) {
			active.responseTimeAlarm = true;
			return;
		}
		active.responseTimeAlarm = false;
		// 请求有数据时
		// 1. 当前数组没有数据
		if (busiLongTimeList.value.length <= 0) {
			const dLenPos = res.data.data.length - 1;
			res.data.data.reverse().forEach((r: anyObj, index: number) => {
				r.pos = dLenPos - index;
				busiLongTimeList.value.splice(0, 0, r);
			});
			return;
		}
		// 2. 当前数组有数据
		refreshAlarmListData(busiLongTimeList, res.data.data, 'pushTime', 8);
	});
}
// 获取区域业务量表格数据
function getAreaBusiData() {
	queryAreaBusinessStatistics({
		startTime: queryParams.startTime,
		endTime: queryParams.endTime,
	}).then((res: ApiResponse) => {
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		if (!res.data) {
			res.data = [];
		}
		fillCity(res.data, geoCoordMap);
		areaBusiDataTemp.value = res.data;
		if (areaBusiDataTemp.value.length > 0) {
			areaBusiTablePage.totalPage = Math.ceil(areaBusiDataTemp.value.length / areaBusiTablePage.pageSize);
			areaBusiTablePage.pageItemWidth = Math.ceil((260 - 100) / areaBusiTablePage.totalPage);
			// 跳转到第一页
			areaBusiTableChangePage(1);
			// 启动定时器翻页
			startAutoChangePageInterval();
		}
	});
}
// 获取地图数据
function getMapBusiData() {
	queryMapAreaBusinessStatistics({
		startTime: areaQueryTime.startTime,
		endTime: areaQueryTime.endTime,
	}).then((res: ApiResponse) => {
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		fillCity(res.data, geoCoordMap);
		const mapData: anyObj[] = [];
		res.data.forEach((t: anyObj) => {
			if (t.healthRate === undefined || t.healthRate === null) {
				t.healthRate = '';
			}
			mapData.push({
				name: t.areaName,
				value: t.healthRate === 100 ? Number(t.healthRate) : t.healthRate,
			});
		});
		renderMap(mapData);
	});
}
// 获取最新健康度告警列表数据
function getHealthAlertList() {
	queryRecentHealthRateAlarm({
		systemId: queryParams.systemId,
		startTime: queryParams.startTime,
		endTime: queryParams.endTime,
		pageNum: 1,
		pageSize: 5,
	}).then((res: ApiResponse) => {
		if (res.code !== 0) {
			active.healthRateAlarm = true;
			return;
		}
		// 都无数据时展示
		if (!(healthAlertList.value.length || res.data.data.length)) {
			active.healthRateAlarm = true;
			return;
		}
		active.healthRateAlarm = false;
		// 请求有数据时
		// 1. 当前数组没有数据
		if (healthAlertList.value.length <= 0) {
			const dLenPos = res.data.data.length - 1;
			res.data.data.reverse().forEach((r: anyObj, index: number) => {
				r.pos = dLenPos - index;
				healthAlertList.value.splice(0, 0, r);
			});
			return;
		}
		// 2. 当前数组有数据
		refreshAlarmListData(healthAlertList, res.data.data.reverse(), 'maxAlarmTime', 5);
	});
}
// 获取系统刷新设置
function getRefreshConfig() {
	queryRefreshConfig().then((res: ApiResponse) => {
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		interval.allRefreshTime = parseInt(res.data.refreshTime);
		finalRefreshVal = parseInt(res.data.refreshTime);
		refreshFlag.value = res.data.refreshFlag.includes('true');
		refreshFlag.value ? startAllRefreshInterval() : stopAllRefreshInterval();
	});
}
// 获取系统下拉列表
function getSystemOption() {
	queryAppSystemOptions({ isStatus: 1 }).then((res: ApiResponse) => {
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		systemOptions.value = res.data;
		queryParams.systemId = systemOptions.value[0].value;
		getHealthAlertList();
		observationRef.value.getBusiAlarmList();
		observationRef.value.getObservationList();
		renderAll();
	});
}
// 获取系统总览数据
function getSystemOverview() {
	oldOverview.value = deepCloneOps(systemOverview.value);
	querySystemOverview({
		dateTime: parseTime(new Date().getTime() - 1000 * 300, '{y}-{m}-{d}'),
	}).then((res: ApiResponse) => {
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		if (firstQuery.value) {
			firstQuery.value = false;
		}
		systemOverview.value = res.data;
	});
}
// 获取系统分类数据
function getSystemDomainOption() {
	querySystemDomainOption().then((res: ApiResponse) => {
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		systemDomainOptions.value = res.data;
		systemDomainOptions.value.unshift({
			systemDomainId: undefined,
			systemDomainName: '全部',
		});
	});
}
// 获取各系统健康度数据
function getSystemHealthArr() {
	getSystemHealthList({
		systemDomainId: systemDomainId.value,
		startTime: queryParams.startTime,
		endTime: queryParams.endTime,
	}).then((res: ApiResponse) => {
		if (res.code !== 0) {
			active.healthRateAlarmNoData = true;
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		systemHealthArrAllData.value = deepCloneOps(res.data);
		systemHealthArr.value = deepCloneOps(res.data);
		if (systemHealthArrAllData.value.length <= 0) {
			active.healthRateAlarmNoData = true;
			return;
		}
		active.healthRateAlarmNoData = false;
		// 画系统健康度饼图
		systemHealthArrAllData.value.forEach((d) => {
			setTimeout(() => {
				renderSystemHealthPie(d);
			});
		});
	});
}

/*3.图表渲染*/
// 清空所有跟随系统切换的图表
function clearAll() {
	observationRef.value.clearChart();
	// 切换系统时,将关键业务的数值展示为none,解决数据异步导致没数据时数值晚几秒才消失
	observationRef.value.dnone = true;
	chart.alertBar.clear();
}
// 渲染所有图
function renderAll() {
	observationRef.value.renderBusinessHealthTopN();
	renderCountLineChart();
}
// 渲染地图
function renderMap(mapData: anyObj[]) {
	const convertData = function (data: anyObj[]) {
		let res = [];
		for (let i = 0; i < data.length; i++) {
			let geoCoord = geoCoordMap[data[i].name];
			if (geoCoord) {
				res.push({
					name: data[i].name,
					value: geoCoord.concat(data[i].value),
				});
			}
		}
		return res;
	};
	chart.map.setOption({
		title: {
			show: false,
		},
		tooltip: {
			trigger: 'item',
			formatter: function (params: anyObj) {
				if (params.value >= 0) {
					return params.name + '：' + params.value + '%';
				} else {
					return params.name;
				}
			},
		},
		visualMap: {
			show: true,
			min: 0,
			max: 100,
			calculable: true, //是否展示拖拽手柄
			realtime: true, //拖拽时是否更新
			orient: 'horizontal', //展现方式
			left: '10%',
			itemWidth: 10,
			itemHeight: 211,
			text: ['', '健康度（%）'],
			textGap: 20,
			color: ['#2a507d', '#ef4b43'],
			textStyle: {
				color: '#FFFFFF',
			},
		},
		geo: {
			map: place,
			roam: true,
			label: {
				// 显示城市标签
				show: true,
				// 城市字体颜色
				color: 'rgb(255, 255, 255)',
			},
			emphasis: {
				label: {
					color: 'rgb(255, 255, 255)',
				},
				// 高亮状态样式
				itemStyle: {
					areaColor: 'rgba(255, 255, 255, 0.1)',
					shadowOffsetX: 0,
					shadowOffsetY: 0,
					shadowBlur: 20,
					borderWidth: 3,
					shadowColor: 'rgba(0, 0, 0, 0.5)',
				},
			},
			itemStyle: {
				// 地图边线颜色
				borderColor: 'rgb(0, 255, 255)',
				// 边线宽度
				borderWidth: 1,
				// 地图底色
				color: '#2a507d',
			},
		},
		series: [
			{
				name: 1, //浮动框的标题
				type: 'map',
				geoIndex: 0,
				nameProperty: 'NAME',
				data: mapData,
			},
			{
				name: 'healthRateTip',
				type: 'scatter',
				coordinateSystem: 'geo',
				symbol: 'circle',
				symbolSize: [1, 1],
				tooltip: {
					show: false,
				},
				label: {
					show: true,
					color: '#ffffff',
					fontSize: 12,
					position: 'bottom',
					formatter(value: anyObj) {
						if (value.data.value[2] !== '') {
							return value.data.value[2] + '%';
						} else {
							return '';
						}
					},
				},
				emphasis: {
					label: {
						color: '#000000',
					},
				},
				itemStyle: {
					color: '#ffffff',
				},
				// 展示对应城市的健康度数值
				data: convertData(mapData),
				showEffectOn: 'render',
				rippleEffect: {
					brushType: 'stroke',
				},
				zlevel: 1,
			},
		],
	});
	// 点击跳转到区域健康度告警分析
	chart.map.on('click', (e: anyObj) => {
		router.push({
			path: '/ops-workbench/area-health/alarm-analysis/index',
			query: {
				cityName: e.name,
			},
		});
	});
}
// 渲染访问量 告警量 昨日访问量 折线图
function renderCountLineChart() {
	// 画图相关参数变量
	let showAxisLabel = true;
	let yAixsIndex = null,
		lineStyle = {},
		mergeData: anyObj | undefined = {};
	const d = JSON.parse(JSON.stringify(queryParams));
	const StartData = new Date(new Date().toLocaleDateString()).getTime();
	const endData = new Date().getTime();
	let type = 0;
	if ((endData - StartData) / 60 / 60 / 1000 <= 12 && trendType.value === 12) {
		type = 2;
	} else {
		type = trendType.value;
	}

	getTrendTimeRange(type, d);
	queryCompleteAlarmTrend(d).then((res: ApiResponse) => {
		chart.alertBar.clear();
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		const resData = res.data;
		// 无数据
		if (!resData || resData.length <= 0) {
			lastNoData.value = true;
			chart.alertBar.clear();
			noDataOption(chart.alertBar, {
				textStyle: { color: '#fff' },
			});
			showAxisLabel = false;
			yAixsIndex = 1;
			lineStyle = {
				color: 'rgba(0,0,0,0)',
			};
		} else {
			if (lastNoData.value) {
				chart.alertBar.clear();
				lastNoData.value = false;
			}
			showAxisLabel = true;
			yAixsIndex = 0;
			lineStyle = {
				color: '#2beded',
			};
			mergeData = mergeTrendData(resData);
		}
		// 渲染图表
		chart.alertBar.setOption({
			// 提示框
			tooltip: {
				show: showAxisLabel,
				trigger: 'axis',
			},
			// 坐标系位置
			grid: {
				x: 60,
				x2: 50,
				y: 30,
				y2: 20,
			},
			// 图例标记
			legend: {
				data: [
					{
						name: '访问量',
						icon: 'roundRect',
					},
					{
						name: '告警量',
						icon: 'roundRect',
					},
					{
						name: '昨日访问量',
						icon: 'roundRect',
					},
				],
				align: 'right',
				left: 'center',
				itemWidth: 20,
				itemHeight: 10,
				itemGap: 20,
				textStyle: {
					color: '#ffffff',
				},
			},
			// x轴
			xAxis: {
				type: 'category',
				data: resData.length > 0 ? mergeData?.resLabelTimeArr : ['00:00', '01:00', '02:00'],
				boundaryGap: true,
				axisLabel: {
					show: showAxisLabel,
				},
				// X坐标轴样式
				axisLine: {
					lineStyle: {
						color: '#ffffff',
					},
				},
				// X轴刻度样式
				axisTick: {
					show: false,
				},
			},
			// y轴
			yAxis: [
				{
					type: 'value',
					// Y坐标轴样式
					axisLine: {
						show: false,
						lineStyle: {
							opacity: 0,
						},
					},
					// Y轴刻度样式
					axisTick: {
						show: false,
					},
					axisLabel: {
						color: '#2beded',
					},
					// 分隔线样式
					splitLine: {
						show: true,
						lineStyle: {
							color: '#ffffff',
						},
					},
				},
				{
					type: 'value',
					minInterval: 1000,
					position: 'left',
					// Y坐标轴样式
					axisLine: {
						show: resData.length <= 0,
						lineStyle: {
							color: '#ffffff',
						},
					},
					// Y轴刻度样式
					axisTick: {
						show: false,
					},
					// 分隔线样式
					splitLine: {
						show: false,
					},
				},
			],
			dataZoom: [
				{
					type: 'inside',
					start: 0,
					end: 100,
				},
			],
			series: [
				{
					name: '访问量',
					type: 'line',
					yAxisIndex: yAixsIndex,
					data: resData.length > 0 ? mergeData?.resCompleteCountArr : [0, 1000, 2000],
					symbol: resData.length > 0 ? 'emptyCircle' : 'none',
					symbolSize: 2,
					smooth: true,
					itemStyle: {
						color: '#2beded',
					},
					// 填充区域
					areaStyle: getAreaStyle('rgb(43, 237, 237)', 1, 0.6).areaStyle,
					lineStyle: lineStyle,
				},
				{
					name: '告警量',
					type: 'line',
					data: resData.length > 0 ? mergeData?.resAlarmCountArr : [],
					symbol: resData.length > 0 ? 'emptyCircle' : 'none',
					symbolSize: 2,
					smooth: true,
					yAxisIndex: 0,
					itemStyle: {
						color: '#fc5678',
					},
					// 填充区域
					areaStyle: getAreaStyle('rgb(252,86,120)', 1, 0.6).areaStyle,
				},
				{
					name: '昨日访问量',
					type: 'line',
					data: resData.length > 0 ? mergeData?.yesterdayCountArr : [],
					symbol: resData.length > 0 ? 'emptyCircle' : 'none',
					symbolSize: 2,
					smooth: true,
					yAxisIndex: 0,
					itemStyle: {
						color: '#ff915a',
					},
					// 填充区域
					areaStyle: getAreaStyle('rgb(255, 145, 90)', 1, 0.6).areaStyle,
				},
			],
		});
		chart.alertBar.off('click');
		chart.alertBar.on('click', (e: anyObj) => {
			if (e.dataIndex === 0) {
				return;
			}
			shareDataStore.addYwgztSysShare({
				arrName: 'labelTimeArr',
				data: mergeData?.resLabelTimeArr,
			});
			shareDataStore.addYwgztSysShare({
				arrName: 'completeCountArr',
				data: mergeData?.resCompleteCountArr,
			});
			shareDataStore.addYwgztSysShare({
				arrName: 'alarmCountArr',
				data: mergeData?.resAlarmCountArr,
			});
			shareDataStore.addYwgztSysShare({
				arrName: 'yesterdayArr',
				data: mergeData?.yesterdayCountArr,
			});
			router.push({
				path: '/ops-workbench/system/operateTrendAnalysis',
				query: {
					trendType: trendType.value,
					systemId: d.systemId,
					tableStartTime: mergeData?.resLabelTimeArr[e.dataIndex - 1],
					tableEndTime: mergeData?.resLabelTimeArr[e.dataIndex],
				},
			});
		});
	});
}
// 归并趋势图数据
function mergeTrendData(arr: []) {
	if (arr.length <= 0) {
		return;
	}
	const resLabelTimeArr: string[] = [],
		resCompleteCountArr: number[] = [],
		resAlarmCountArr: number[] = [],
		yesterdayCountArr: number[] = [];
	// 最近一小时不做自适应
	arr.forEach((r: anyObj) => {
		resLabelTimeArr.push(r.cycleTime.substring(11, 16));
		resCompleteCountArr.push(r.visitCount);
		resAlarmCountArr.push(r.alarmCount);
		yesterdayCountArr.push(r.yesterdayCount);
	});
	return {
		resLabelTimeArr,
		resCompleteCountArr,
		resAlarmCountArr,
		yesterdayCountArr,
	};
}
// 渲染下拉框-系统健康度饼图
function renderSystemHealthPie(d: anyObj) {
	const myChart = echarts.init(document.getElementById('chart-' + d.systemId) as HTMLElement);
	const hdSystemId = d.systemId;
	const hdSystemName = lineFeed(d.systemName, 9, 2);
	const hd = d.healthRate === 100 ? Number(d.healthRate) : d.healthRate;
	const hdArr = [hd / 100, hd / 100];
	myChart.clear();
	myChart.setOption({
		title: {
			text: hd + '{a|%}',
			textStyle: {
				fontSize: 20,
				fontFamily: 'Microsoft Yahei',
				fontWeight: 'normal',
				color: '#ffffff',
				rich: {
					a: {
						fontSize: 20,
					},
				},
			},
			x: 'center',
			y: '45%',
		},
		tooltip: {
			show: true,
			formatter: lineFeed(d.systemName, 9, 20, 2, '<br />'),
			confine: true,
		},
		graphic: [
			{
				type: 'group',
				left: 'center',
				top: '85%',
				children: [
					{
						type: 'text',
						z: 100,
						left: '10',
						top: 'middle',
						style: {
							fill: '#ffffff',
							text: hdSystemName,
							fontSize: 14,
						},
					},
				],
			},
		],
		series: [
			{
				type: 'liquidFill',
				radius: '70%',
				center: ['50%', '50%'],
				data: hdArr,
				backgroundStyle: {
					color: 'rgba(134, 228, 245, 0.2)',
				},
				outline: {
					borderDistance: 0,
					itemStyle: {
						borderWidth: 12,
						borderColor: {
							type: 'linear',
							x: 0,
							y: 0,
							x2: 0,
							y2: 1,
							colorStops: [
								{
									offset: 0,
									color: '#427ed7',
								},
								{
									offset: 0.5,
									color: '#66b5e7',
								},
								{
									offset: 1,
									color: '#85e2f5',
								},
							],
							globalCoord: false,
						},
						shadowBlur: 10,
						shadowColor: '#000',
					},
				},
				// 水波浪的颜色及透明度
				color: ['#49a5bf', '#34fdff'],
				itemStyle: {
					opacity: 0.8,
				},
				label: {
					formatter: '',
				},
			},
		],
	});
	myChart.getZr().on('click', (params: any) => {
		queryParams.systemId = hdSystemId;
		handleSystemChange();
	});
	myChart.getZr().on('mousemove', (params: any) => {
		myChart.dispatchAction({
			type: 'showTip',
			seriesIndex: 0,
			dataIndex: 0,
			position: [params.event.offsetX, params.event.offsetY],
		});
	});
}

/*4.页面交互*/
// 切换趋势图的显示时间范围
function toggleTrendScale(val: number) {
	trendType.value = val;
	renderCountLineChart();
}
// 三个实时告警的更多-打开弹框
function handleToRealTimeAlarm(flag: number) {
	switch (flag) {
		case 1:
			realtimeDialogTitle.value = '最新响应慢业务告警';
			break;
		case 2:
			realtimeDialogTitle.value = '最新失败业务告警';
			break;
		case 3:
			realtimeDialogTitle.value = '最新健康度业务告警';
			break;
	}
	const currentDate = new Date();
	queryParams.startTime = parseTime(currentDate.getTime(), '{y}-{m}-{d}') + ' 00:00:00';
	queryParams.endTime = parseTime(currentDate.getTime(), '{y}-{m}-{d} {h}:{i}:00');
	realTimeParam.value = {
		...queryParams,
		dialogType: flag,
	};
	realtimeDialogOpen.value = true;
}
// 打开弹框
function handleOpenRealtimeDialog() {
	realtimeDialog.value.handleSearch();
}
// 关闭弹框
function handleCloseRealtimeDialog() {
	realtimeDialogKey.value = randomUUID();
}
function setDialogClose() {
	realtimeDialogOpen.value = false;
}
// 三个实时告警的各项下钻--告警事件归档分析页面
function jumpToAlarmAnalysis(item: anyObj, flag: string) {
	let titleTxt = '';
	switch (flag) {
		case '1':
			if (item.dataType === 3) {
				titleTxt = '共用步骤-' + item.stepName + '-响应慢业务告警分析';
			} else if (item.dataType === 4) {
				titleTxt = '共用接口-' + item.stepName + '-响应慢业务告警分析';
			} else {
				titleTxt = item.systemName + '-' + item.businessName + '-响应慢业务告警分析';
			}
			break;
		case '2':
			if (item.dataType === 3) {
				titleTxt = '共用步骤-' + item.stepName + '-失败业务告警分析';
			} else if (item.dataType === 4) {
				titleTxt = '共用接口-' + item.stepName + '-失败业务告警分析';
			} else {
				titleTxt = item.systemName + '-' + item.businessName + '-失败业务告警分析';
			}
			break;
		case '3':
			titleTxt = item.systemName + '-' + item.businessName + '-健康度低业务告警分析';
			break;
	}
	router.push({
		path: '/ops-workbench/business-alarm-analysis/index',
		query: {
			titleName: titleTxt,
			trendId: flag,
			areaId: flag,
			id: item.id,
			systemId: item.systemId,
			businessCode: item.businessCode,
			businessName: item.businessName,
			stepCode: item.stepCode,
			stepName: item.stepName,
			startTime: item.startTime,
			cycleTime: item.endTime,
			endTime: item.endTime,
			systemName: item.systemName,
			groupId: item.groupId,
			alarmIndicatorCode: item.alarmIndicatorCode,
			dataType: item.dataType,
		},
	});
}

// 搜索系统-弹框显示时触发
function handleSystemSearchShow() {
	getSystemHealthArr();
}
// 点击系统筛选或选中某个域时
function handleSearchSystemHealth(value: string | number) {
	if (value !== 'filter') {
		// 选中域时
		systemDomainId.value = value;
	}
	active.healthRateAlarmNoData = false;
	// 根据域
	if (systemDomainId.value! >= 0) {
		systemHealthArr.value = systemHealthArrAllData.value.filter((d: anyObj) => d.systemDomainId === systemDomainId.value);
	} else {
		systemHealthArr.value = deepCloneOps(systemHealthArrAllData.value);
	}
	// 根据系统名称
	systemHealthArr.value = systemHealthArr.value.filter((d) => d.systemName.includes(querySystemName.value));
	if (systemHealthArr.value.length <= 0) {
		active.healthRateAlarmNoData = true;
		return;
	}
	proxy.$nextTick(() => {
		systemHealthArr.value.forEach((d) => {
			renderSystemHealthPie(d);
		});
	});
}
// 系统下拉框值改变
function handleSystemChange() {
	// 初始化请求参数
	initParams();
	// 清空最新健康度告警列表的数据
	healthAlertList.value = [];
	// 请求跟随系统变化的数据
	getHealthAlertList();
	observationRef.value.getBusiAlarmList();
	observationRef.value.getObservationList();
	// 清空所有图表(为了动态效果,仅在无数据的时候清空了,所以切换系统需要清空一下)
	clearAll();
	// 渲染图表
	renderAll();
}
// 刷新弹窗展示时
function handleRefreshShow() {
	increaseEle.value = document.getElementsByClassName('el-input-number__increase')[0] as HTMLElement;
	decreaseEle.value = document.getElementsByClassName('el-input-number__decrease')[0] as HTMLElement;
	increaseEle.value.addEventListener('mouseup', awaitUpdateRefresh);
	decreaseEle.value.addEventListener('mouseup', awaitUpdateRefresh);
}
// 延时调用更新
function awaitUpdateRefresh() {
	setTimeout(() => {
		updateRefresh();
	});
}
// 刷新时间值改变处理
function onRefreshChange() {
	if (finalRefreshVal === interval.allRefreshTime) {
		return;
	}
	updateRefresh();
}
// 修改刷新设置
function updateRefresh() {
	updateRefreshConfig({
		refreshTime: '' + interval.allRefreshTime,
		refreshFlag: '' + refreshFlag.value,
	}).then((res) => {
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		proxy.$modal.msgSuccess('设置成功!');
		refreshFlag.value ? startAllRefreshInterval() : stopAllRefreshInterval();
		finalRefreshVal = interval.allRefreshTime;
	});
}
// 区域业务量表格跳转页
function areaBusiTableChangePage(p: number) {
	areaBusiTablePage.pageNum = p;
	areaBusiData.value = areaBusiDataTemp.value.slice((p - 1) * areaBusiTablePage.pageSize, p * areaBusiTablePage.pageSize);
}
// 启动定时器翻页
function startAutoChangePageInterval() {
	// 确保定时器已销毁
	clearInterval(interval.autoChangePage);
	interval.autoChangePage = setInterval(() => {
		let p = areaBusiTablePage.pageNum + 1;
		if (p > areaBusiTablePage.totalPage) {
			p = 1;
		}
		areaBusiTableChangePage(p);
	}, 5000);
}
// 全局刷新
function allRefresh() {
	// 初始化请求参数
	initParams();
	// 请求数据
	// getBusiFailList();
	// getBusiLongTimeList();
	getAreaBusiData();
	getMapBusiData();
	getHealthAlertList();
	observationRef.value.getBusiAlarmList();
	observationRef.value.getObservationList();
	getSystemOverview();
	// 渲染图表
	renderAll();
}
// 历史告警
function jumpToHisAlarm() {
	router.push({
		path: '/ops-workbench/historicalAlarmQuery/index',
		query: {
			systemId: queryParams.systemId,
		},
	});
}
// 切换
function switchTab() {
	showObservationArea.value = !showObservationArea.value;
}
// 启动定时器全局刷新
function startAllRefreshInterval() {
	// 确保定时器已销毁
	stopAllRefreshInterval();
	allRefresh();
	countdown.value = interval.allRefreshTime;
	interval.allRefresh = setInterval(() => {
		countdown.value--;
		if (countdown.value < 0) {
			allRefresh();
			countdown.value = interval.allRefreshTime;
		}
	}, 1000);
}
// 关闭全局刷新定时器
function stopAllRefreshInterval() {
	clearInterval(interval.allRefresh);
}

let websocFailArr: anyObj[] = [],
	websocTimeArr: anyObj[] = [];
//初始化weosocket
function initWebSocket() {
	if (typeof WebSocket === 'undefined') {
		alert('您的浏览器不支持WebSocket');
		return false;
	}
	const tenant = useUserStore().userInfo.tenantId ? useUserStore().userInfo.tenantId : 1;
	const wsuri =
		'ws://' +
		location.host +
		'/ops-workbench/ws/info?access_token=' +
		useUserStore().access_token +
		'&TENANT-ID=' +
		tenant +
		'&nowDate=' +
		Date.parse(new Date()); // websocket地址
	websock = new WebSocket(wsuri);
	websock.onopen = websocketonopen;
	websock.onmessage = websocketonmessage;
	websock.onerror = websocketonerror;
	websock.onclose = websocketclose;
}
// 192
//连接成功
function websocketonopen() {
	console.log('WebSocket连接成功');
	// 添加心跳检测，每隔一定时间发一次数据，防止连接断开（这跟服务器的设置有关，如果服务器没有设置每隔多长时间不发消息断开，可以不进行心跳设置）
	// this.timer = setInterval(() => {
	//   try {
	//     websock.send('test')
	//     console.log('发送消息');
	//   }catch(err){
	//     console.log('断开了：' + err);
	//     connection()
	//   }
	// }, 1000 * interval.allRefreshTime)
}
// 接收后端返回的数据
function websocketonmessage(e: any) {
	let res = JSON.parse(e.data);
	if (res.code !== 0) {
		active.failRateAlarm = true;
		active.responseTimeAlarm = true;
		return;
	}
	// 都无数据时展示
	if (!busiFailList.value.length) {
		active.failRateAlarm = true;
	}
	if (!busiLongTimeList.value.length) {
		active.responseTimeAlarm = true;
	}
	if (!res.data) {
		return;
	}
	if (res.data.fileType === 'BS_FAIL_RATE_10') {
		// 失败率
		websocFailArr.push(res.data);
	} else if (res.data.fileType === 'BS_FAIL_RATE_20') {
		// 响应慢
		websocTimeArr.push(res.data);
	}
	// 请求有数据时 (考虑同时来几条数据导致展示堆叠的情况)
	setTimeout(() => {
		if (websocFailArr.length > 0) {
			active.failRateAlarm = false;
			const copyWebsocDataArr = websocFailArr.splice(0, websocFailArr.length);
			// 1. 当前数组没有数据
			if (busiFailList.value.length <= 0) {
				const dLenPos = copyWebsocDataArr.length - 1;
				copyWebsocDataArr.reverse().forEach((r, index) => {
					r.pos = dLenPos - index;
					busiFailList.value.splice(0, 0, r);
				});
				return;
			}
			// 2. 当前数组有数据
			refreshAlarmListData(busiFailList, copyWebsocDataArr, 'pushTime', 8);
		}
		if (websocTimeArr.length > 0) {
			active.responseTimeAlarm = false;
			const copyWebsocDataArr = websocTimeArr.splice(0, websocTimeArr.length);
			// 1. 当前数组没有数据
			if (busiLongTimeList.value.length <= 0) {
				const dLenPos = copyWebsocDataArr.length - 1;
				copyWebsocDataArr.reverse().forEach((r, index) => {
					r.pos = dLenPos - index;
					busiLongTimeList.value.splice(0, 0, r);
				});
				return;
			}
			// 2. 当前数组有数据
			refreshAlarmListData(busiLongTimeList, copyWebsocDataArr, 'pushTime', 8);
		}
	}, 500);
}
//连接建立失败重连
function websocketonerror(e: anyObj | string) {
	console.log(`连接失败的信息：`, e);
	initWebSocket(); // 连接失败后尝试重新连接
}
//关闭连接
function websocketclose(e: anyObj | string) {
	console.log('断开连接', e);
}

// 初始化请求参数
initParams();
// 请求页面所有数据
// getAllData();
// 建立websocket链接
initWebSocket();
</script>

<style rel="stylesheet/scss" lang="scss">
@import '@/styles/ops-workbench/common.scss';
@import '@/styles/ops-workbench/yd-table.scss';
/*el-popover弹框*/
.search-system-popover {
	background-color: rgba(29, 44, 83, 0.9) !important;
	border-color: #5acce0 !important;
}
.search-system-popover[x-placement^='bottom'] .popper__arrow {
	border-bottom-color: #5accee !important;
}
.search-system-popover[x-placement^='bottom'] .popper__arrow::after {
	border-bottom-color: #5acce0 !important;
	top: -1px;
}
.el-popper.is-light .el-popper__arrow::before {
	background-color: transparent;
	border-top: 1px solid #5acce0;
}
</style>
<style rel="stylesheet/scss" lang="scss" scoped>
@import '@/styles/ops-workbench/ywgzt-index.scss';

.h-100 {
	height: 100%;
}
.ywgzt-container {
	height: 100vh;
	width: 100%;
	padding: 10px;
	overflow: hidden;
}
.business-list-body {
	position: relative;
}
.business-list-item {
	width: 100%;
	position: absolute;
	transition-property: width, top, transform;
	transition-duration: 0.3s, 0.5s, 0.5s;
}
.health-list-body {
	position: relative;
}
.health-list-item {
	width: 100%;
	position: absolute;
	transition-property: width, top, transform;
	transition-duration: 0.3s, 0.5s, 0.5s;
}

.flip-list-enter {
	opacity: 0;
	transform: translateY(-100px);
}
.flip-list-leave-to {
	transition: unset;
}

.transition-0 {
	top: 0%;
}
.transition-1 {
	top: 12.5%;
}
.transition-2 {
	top: 25%;
}
.transition-3 {
	top: 37.5%;
}
.transition-4 {
	top: 50%;
}
.transition-5 {
	top: 62.5%;
}
.transition-6 {
	top: 75%;
}
.transition-7 {
	top: 87.5%;
}

.healthTransition-0 {
	top: 0%;
}
.healthTransition-1 {
	top: 20%;
}
.healthTransition-2 {
	top: 40%;
}
.healthTransition-3 {
	top: 60%;
}
.healthTransition-4 {
	top: 80%;
}

.countdown-clock {
	margin-left: 0.5rem;
	position: relative;
	display: inline-block;
	width: 32px;
	height: 32px;
	line-height: 31px;
	text-align: center;
	border-radius: 50%;
}

.countdown-clock:before {
	position: absolute;
	margin-left: -0.5rem;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	content: ' ';
	clip: rect(0, 32px, 5px, 0);
	box-shadow: inset -5px 0 0 5px #fff;
	color: #2beded;
	-webkit-animation: rotator 1s infinite linear;
	animation: rotator 1s infinite linear;
}

@-webkit-keyframes rotator {
	0% {
		-webkit-transform: rotate(-180deg);
		transform: rotate(-180deg);
		box-shadow: inset -1px 0 0 1px #49eaf2;
	}
	50% {
		-webkit-transform: rotate(0deg);
		transform: rotate(0deg);
		box-shadow: inset -1px 0 0 1px rgb(197, 233, 247);
	}
	100% {
		-webkit-transform: rotate(180deg);
		transform: rotate(180deg);
		box-shadow: inset -1px 0 0 1px rgb(114, 248, 241);
	}
}
@keyframes rotator {
	0% {
		-webkit-transform: rotate(-180deg);
		transform: rotate(-180deg);
		box-shadow: inset -1px 0 0 1px #49eaf2;
	}
	50% {
		-webkit-transform: rotate(0deg);
		transform: rotate(0deg);
		box-shadow: inset -1px 0 0 1px rgb(197, 233, 247);
	}
	100% {
		-webkit-transform: rotate(180deg);
		transform: rotate(180deg);
		box-shadow: inset -1px 0 0 1px rgb(114, 248, 241);
	}
}
</style>
